home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / AUTOSYM.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  14KB  |  466 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.4  $
  6. //
  7. // OLE Automation Server Implementation, except TServedObject (in typelib.cpp)
  8. //----------------------------------------------------------------------------
  9. #include <ocf/pch.h>
  10. #if !defined(OCF_APPDESC_H)
  11. # include <ocf/appdesc.h>
  12. #endif
  13. #if !defined(OCF_OCREG_H)
  14. # include <ocf/ocreg.h>
  15. #endif
  16. #if !defined(OCF_OCCTRL_H) && defined(BI_PLAT_WIN32)
  17. # include <ocf/occtrl.h>
  18. #endif
  19.  
  20. #if defined(BI_NAMESPACE)
  21. namespace OCF {
  22. #endif
  23.  
  24. TAutoType TAutoVoid       ::ClassInfo = {atVoid};
  25. TAutoType TAutoByte       ::ClassInfo = {atByte};
  26. TAutoType TAutoShort      ::ClassInfo = {atShort};
  27. TAutoType TAutoLong       ::ClassInfo = {atLong};
  28. TAutoType TAutoFloat      ::ClassInfo = {atFloat};
  29. TAutoType TAutoDouble     ::ClassInfo = {atDouble};
  30. TAutoType TAutoCurrency   ::ClassInfo = {atCurrency};
  31. TAutoType TAutoDate       ::ClassInfo = {atDatetime};
  32. TAutoType TAutoString     ::ClassInfo = {atString};
  33. TAutoType TAutoBool       ::ClassInfo = {atBool};
  34. TAutoType TAutoUnknown    ::ClassInfo = {atUnknown};
  35. TAutoType TAutoDispatch   ::ClassInfo = {atObject};
  36. TAutoType TAutoVariant    ::ClassInfo = {atVariant};
  37. TAutoType TAutoSafeArray  ::ClassInfo = {atSafeArray};
  38. TAutoType TAutoShortRef   ::ClassInfo = {atByRef|atShort};
  39. TAutoType TAutoLongRef    ::ClassInfo = {atByRef|atLong};
  40. TAutoType TAutoFloatRef   ::ClassInfo = {atByRef|atFloat};
  41. TAutoType TAutoDoubleRef  ::ClassInfo = {atByRef|atDouble};
  42. TAutoType TAutoCurrencyRef::ClassInfo = {atByRef|atCurrency};
  43. TAutoType TAutoDateRef    ::ClassInfo = {atByRef|atDatetime};
  44. TAutoType TAutoStringRef  ::ClassInfo = {atByRef|atString};
  45. TAutoType TAutoVariantRef ::ClassInfo = {atByRef|atVariant};
  46. TAutoType TAutoBoolRef    ::ClassInfo = {atByRef|atBool};
  47. TAutoType TAutoByteRef    ::ClassInfo = {atByRef|atByte};
  48.  
  49. void _OCFFUNC SendObituary(const void far* obj, const typeinfo& typeInfo)
  50. {
  51.   TAppDescriptor* appDesc = NS_OCF::GetAppDescriptor();
  52.   if (appDesc)
  53.     appDesc->InvalidateObject(NS_OCF::MostDerived(obj, typeInfo));
  54. }
  55.  
  56. #if defined(BI_NAMESPACE)
  57. } // namespace OCF
  58. #endif
  59.  
  60. //----------------------------------------------------------------------------
  61. // TAutoClass implementation
  62. //
  63.  
  64. TAutoClass::TClassList TAutoClass::ClassList = {0,0,0};// MUST BE MODULE GLOBAL
  65.  
  66. TAutoClass::TAutoClass(TAutoSymbol* table, TAutoSymbol* classSymbol,
  67.              const typeinfo& typeInfo, TAggregator aggregator)
  68.            : Table(table), ClassSymbol(classSymbol), TypeInfo(typeInfo),
  69.              Aggregator(aggregator), AutoIds (TRUE)
  70. {
  71.   Type = atObject | atAutoClass;
  72.   NextClass = ClassList.List;
  73.   ClassList.List = this;
  74.   ClassList.Count++;
  75. }
  76.  
  77. TAutoClass::~TAutoClass()  // do we really need to support dynamic AutoClass?
  78. {
  79.   for (TAutoClass** link = &ClassList.List; *link != 0; link = &(*link)->NextClass)
  80.     if (*link == this) {
  81.       *link = NextClass;
  82.       break;
  83.     }
  84. }
  85.  
  86. short TAutoClass::CountCommands()
  87. {
  88.   TAutoSymbol* sym;
  89.   if (!CommandCount) {
  90.     for (sym = Table; !sym->IsTerminator(); sym++) {
  91.       int attr = sym->GetFlags();
  92.       if (attr & asAnyCommand) {
  93.         CommandCount++;
  94.         if (attr & asOleType) {
  95.           if ((attr & asGetSet) == asGetSet)
  96.             VariableCount++;
  97.           else
  98.             FunctionCount++;
  99.         }
  100.       } else if (sym->TestFlag(asClass)) {
  101.         TAutoClass* cls = sym->GetClass();
  102.         if (!sym->SymCount)
  103.           sym->SymCount = cls->CountCommands();
  104.         CommandCount  += cls->CommandCount;
  105.         VariableCount += cls->VariableCount;
  106.         FunctionCount += cls->FunctionCount;
  107.       }
  108.     }
  109.   }
  110.   return CommandCount;
  111. }
  112.  
  113. TAutoSymbol* TAutoClass::FindId(long id, ObjectPtr& obj)
  114. {
  115.   TAutoSymbol* sym;
  116.   long cmdId;
  117.   if ((id <= 0) || !(AutoIds)) {
  118.     // reserved dispatch ID if negative or zero or AutoIDs is false
  119.     for (sym = Table; !sym->IsTerminator(); sym++) {
  120.       if (sym->TestFlag(asAnyCommand) && sym->DispId == id)
  121.         return sym;
  122.  
  123.       if (sym->TestFlag(asClass)) {
  124.         ObjectPtr adjObj = sym->Convert(obj);  // this pointer adjustment
  125.         TAutoSymbol* fsym = sym->GetClass()->FindId(id, adjObj);
  126.         if (fsym) {
  127.           obj = adjObj;
  128.           return fsym;
  129.         }
  130.       }
  131.     }
  132.   } else {
  133.     for (cmdId = 0, sym = Table; !sym->IsTerminator(); sym++) {
  134.       if (sym->TestFlag(asClass)) {
  135.         if (!sym->SymCount)
  136.           sym->SymCount = sym->GetClass()->CountCommands();
  137.         if (cmdId + sym->SymCount >= id) {    // symbol in nested class
  138.           obj = sym->Convert(obj);
  139.           return sym->GetClass()->FindId(id-cmdId, obj);
  140.         }
  141.         cmdId += sym->SymCount;
  142.       }
  143.       else if (sym->TestFlag(asAnyCommand)) {
  144.         cmdId++;
  145.         if (cmdId == id) {
  146.           if (sym->DispId == -1)
  147.             return sym;
  148.           else
  149.             break;
  150.         }
  151.       }
  152.     }
  153.   }
  154.   return 0;
  155. }
  156.  
  157. TAutoSymbol* TAutoClass::FindFunction(unsigned index, MEMBERID& retId)
  158. {
  159.   TAutoSymbol* sym;
  160.   int funcCount = 0;
  161.   long cmdId = retId;
  162.   for (sym = Table; !sym->IsTerminator(); sym++) {
  163.     int attr = sym->GetFlags();
  164.     if (attr & asAnyCommand) {
  165.       cmdId++;
  166.       if ((attr & asOleType) != 0 && (attr & asGetSet) != asGetSet) {
  167.         if (funcCount++ == index) {
  168.           retId = (sym->DispId == -1L) ? cmdId : sym->DispId;
  169.           return sym;
  170.         }
  171.       }
  172.     } else if (sym->TestFlag(asClass)) {
  173.       TAutoClass* cls = sym->GetClass();
  174.       if (!sym->SymCount)
  175.         sym->SymCount = cls->CountCommands();
  176.       if (funcCount + cls->FunctionCount > index) {
  177.         retId = int(cmdId);
  178.         return cls->FindFunction(index - funcCount, retId);
  179.       }
  180.       funcCount += cls->FunctionCount;
  181.       cmdId     += cls->CommandCount;
  182.     }
  183.   }
  184.   return 0;  // should never happen unless caller overruns total count
  185. }
  186.  
  187. TAutoSymbol* TAutoClass::FindVariable(unsigned index, MEMBERID& retId)
  188. {
  189.   TAutoSymbol* sym;
  190.   int varCount = 0;
  191.   long cmdId = retId;
  192.   for (sym = Table; !sym->IsTerminator(); sym++) {
  193.     int attr = sym->GetFlags();
  194.     if (attr & asAnyCommand) {
  195.       cmdId++;
  196.       if ((attr & asGetSet) == asGetSet) {
  197.         if (varCount++ == index) {
  198.           retId = (sym->DispId == -1L) ? cmdId : sym->DispId;
  199.           return sym;
  200.         }
  201.       }
  202.     } else if (sym->TestFlag(asClass)) {
  203.       TAutoClass* cls = sym->GetClass();
  204.       if (!sym->SymCount)
  205.         sym->SymCount = cls->CountCommands();
  206.       if (varCount + cls->VariableCount > index) {
  207.         retId = int(cmdId);
  208.         return cls->FindVariable(index - varCount, retId);
  209.       }
  210.       varCount += cls->VariableCount;
  211.       cmdId    += cls->CommandCount;
  212.     }
  213.   }
  214.   return 0;  // should never happen unless caller overruns total count
  215. }
  216.  
  217. short TAutoClass::GetArgCount(TAutoSymbol& sym)
  218. {
  219.   short count = 0;
  220.   TAutoSymbol* arg = &sym;
  221.   while ((++arg)->TestFlag(asArgument))
  222.     count++;
  223.   return count;
  224. }
  225.  
  226. TAutoSymbol* TAutoClass::Lookup(char far* name, TLangId lang, short symflags,
  227.                                 long far& retid)
  228. {
  229.   long cmdId = 0;
  230.   for (TAutoSymbol* sym = Table; !sym->IsTerminator(); sym++) {
  231.     if (sym->TestFlag(asAnyCommand))
  232.       cmdId++;
  233.     if (sym->TestFlag(symflags) && sym->Name.Compare(name, lang) == 0) {
  234.       retid = sym->DispId == -1 ? cmdId : sym->DispId;
  235.       return sym;
  236.     }
  237.     else if (sym->TestFlag(asClass)) {
  238.       TAutoClass* cls = sym->GetClass();
  239.       if (!sym->SymCount)
  240.         sym->SymCount = cls->CountCommands();
  241.       long id;
  242.       TAutoSymbol* found = cls->Lookup(name, lang, symflags, id);
  243.       if (found) {
  244.         retid = id > 0 ? id + (long)cmdId : id;
  245.         return found;
  246.       }
  247.       cmdId += sym->SymCount;
  248.     }
  249.   }
  250.   return 0;
  251. }
  252.  
  253. TAutoSymbol* TAutoClass::LookupArg(char far* name, TLangId lang,
  254.                                    TAutoSymbol* sym, long far& retid)
  255. {
  256.   PRECONDITION(sym);
  257.  
  258.    for (int i = 0; (++sym)->TestFlag(asArgument); ++i)
  259.      if (sym->Name.Compare(name, lang) == 0) {
  260.        retid = (long)i;
  261.        return sym;
  262.      }
  263.    return 0;
  264. }
  265.  
  266. TXAuto::TError TAutoClass::Dispatch(ObjectPtr obj, TAutoCreator& creator,
  267.                                     TUnknown& owner, int attr,
  268.                                     TAutoStack& args, TAutoVal* retval)
  269. {
  270.   TAutoCommand*  cmdobj = 0;
  271.   TAutoIterator* iterator = 0;
  272.   try {
  273.     if (args.Symbol->IsIterator()) {
  274.       iterator = args.Symbol->BuildIter(obj, creator, owner, args.LangId);
  275.       iterator->SetSymbol(args.Symbol);
  276.       iterator->Init();
  277.       *retval = (IUnknown*)*iterator; // remains until RefCnt->0
  278.     } else {
  279.       cmdobj = args.Symbol->Build(obj, attr, args);
  280.       cmdobj->SetSymbol(args.Symbol);
  281.       if (args.ArgCount>0 && !cmdobj->Validate()) {// no validate for prop get
  282.         delete cmdobj;
  283.         return TXAuto::xValidateFailure;
  284.       }
  285.       cmdobj->Invoke();
  286.       if ((args.ErrorCode = cmdobj->Report()) != 0) {
  287.         args.ErrorMsg = TAutoCommand::LookupError(args.ErrorCode);
  288.         if (!args.ErrorMsg && args.Symbol)  // if no error message available
  289.           args.ErrorMsg = args.Symbol->Name.Translate(args.LangId);
  290.         delete cmdobj;
  291.         return TXAuto::xErrorStatus;
  292.       }
  293.       if (retval) {
  294.         cmdobj->Return(*retval);
  295.         if (args.Symbol->IsEnum())
  296.           args.Symbol->GetEnum()->Convert(*retval, args.LangId);
  297.         TObjectDescriptor objDesc;
  298.         if (retval->GetObjDesc(objDesc)) {
  299.           if (!objDesc.Object)     // null pointer returned from function
  300.             // there are three choices for behavior here:
  301.             // 1. Allow a dead object to be returned, fail when passed back
  302.             // 2. Fail now, however this prevents testing for null pointer
  303.             // 3. Return an empty variant, causing script to fail when used
  304.             *retval = TAutoVoid();  // return an empty value if no object
  305.           else
  306.             *retval = creator.CreateDispatch(objDesc);
  307.         }
  308.       }
  309.       delete cmdobj;
  310.     }
  311.   }
  312.   catch(TXAuto& xobj) {
  313.     delete cmdobj;
  314.     delete iterator;
  315.     return xobj.ErrorCode;
  316.   }
  317.   return TXAuto::xNoError;
  318. }
  319.  
  320. TAutoClass::TExtLink::TExtLink(TClassList* list, HINSTANCE module)
  321.            : Classes(list), Module(module), Next(0)
  322. {
  323.   for (Prev = &ClassList.Link; *Prev; Prev = &(*Prev)->Next)
  324.     ;               // link to end of list
  325. }
  326.  
  327. TAutoClass::TExtLink::~TExtLink()
  328. {
  329.   *Prev = Next;
  330.   if (Next)
  331.     Next->Prev = Prev;
  332. }
  333.  
  334. //
  335. //
  336. //
  337. int
  338. TAutoClass::TClassList::CountAutoClasses()
  339. {
  340.   int count = Count;
  341.   for (TExtLink* link = Link; link; link = link->Next)
  342.     count += link->Classes->CountAutoClasses();
  343.   return count;
  344. }
  345.  
  346. //
  347. //
  348. //
  349. TAutoClass::TAutoClassRef*
  350. TAutoClass::TClassList::MergeAutoClasses(TAutoClass::TAutoClassRef* array)
  351. {
  352.   for (TAutoClass* cls = List; cls; cls = cls->NextClass, array++)
  353.     array->Class = cls;
  354.   for (TExtLink* link = Link; link; link = link->Next)
  355.     array = link->Classes->MergeAutoClasses(array);
  356.   return array;
  357. }
  358.  
  359. // ----------------------------------------------------------------------
  360. //  Helper routines
  361. //
  362.  
  363. #if defined(BI_NAMESPACE)
  364. namespace OCF {
  365. #endif
  366.  
  367. //
  368. //
  369. TAutoCommand* _OCFFUNC
  370. AutoQuitBuild(ObjectPtr obj, int/*attr*/, TAutoStack& args)
  371. {
  372.   TServedObject& owner = *args.Owner;
  373.  
  374.   // if the automation object is not in control of the app, execute a no-op
  375.   //
  376.   if (owner.Destruct == TObjectDescriptor::Quiet)
  377.     return new TAutoCommand(0);
  378.  
  379.   // if registered as the active object, free it to release OLE's refcnt
  380.   //
  381.   if (owner.Creator.AppDesc.IsActiveObject(&owner))
  382.     owner.Creator.AppDesc.UnregisterObject();
  383.  
  384.   // disconnect automation from app to prevent further access
  385.   //
  386.   owner.Object = 0;
  387.   owner.RootObject = 0;
  388.  
  389.   // build command object for destructor, will either delete or PostQuitMsg
  390.   //
  391.   return owner.Class->GetDestructor()(obj, owner.Destruct);
  392. }
  393.  
  394. #if defined(BI_NAMESPACE)
  395. } // namespace OCF
  396. #endif
  397.  
  398. //
  399. // Temporary defines for using typeinfo with dynamic cast
  400. //
  401. void* __cdecl __DynamicCast(void* object, void* vtable,
  402.                             void* srctyp, void* dsttyp,
  403.                             int reference = 0);
  404. struct tpid {int s; short m; short n; int VptrOffs; int Flags;};  // partial
  405. #define CF_HAS_FARVPTR  0x1000
  406.  
  407. #if defined(BI_NAMESPACE)
  408. namespace OCF {
  409. #endif
  410.  
  411. //
  412. //
  413. const void*
  414. _OCFFUNC DynamicCast(const void* obj, const typeinfo& src, const typeinfo& dst)
  415. {
  416.   int vtblOff;
  417.   if (!obj)
  418.     return obj;
  419.   else if ((vtblOff = src.tpp->VptrOffs) == -1)
  420.     return src==dst ? obj : 0;
  421.   else if (src.tpp->Flags & CF_HAS_FARVPTR)
  422.     return __DynamicCast(const_cast<void far*>(obj),
  423.                          *(void far**)((char*)obj+vtblOff), src.tpp, dst.tpp);
  424.   else
  425.     return __DynamicCast(const_cast<void far*>(obj),
  426.                          *(void near**)((char*)obj+vtblOff), src.tpp,dst.tpp);
  427. }
  428.  
  429. //
  430. //
  431. const void far*
  432. MostDerived(const void far* obj, const typeinfo& src)
  433. {
  434.   int vtblOff;
  435.   if (!obj || (vtblOff = src.tpp->VptrOffs) == -1)
  436.     return obj;
  437.  
  438.   else if (src.tpp->Flags & CF_HAS_FARVPTR)
  439.     return __DynamicCast(const_cast<void far*>(obj),
  440.                          *(void far**)((char*)obj+vtblOff), src.tpp, 0);
  441.   else
  442.     return __DynamicCast(const_cast<void far*>(obj),
  443.                          *(void near**)((char*)obj+vtblOff), src.tpp, 0);
  444. }
  445.  
  446. #if defined(BI_NAMESPACE)
  447. } // namespace OCF
  448. #endif
  449.  
  450. //____________________________________________________________________________
  451. //
  452. // TAutoCommand implementation - inlined to allow definition of _AUTOCLASS
  453. //____________________________________________________________________________
  454.  
  455. #if defined(BI_NAMESPACE)
  456. namespace OCF {
  457. #endif
  458.  
  459. TAutoCommand::TErrorMsgHook _OCFDATA TAutoCommand_ErrorLookup = 0; // module static
  460. TAutoCommand::TCommandHook  _OCFDATA TAutoCommand_InvokeHook  = 0; // module static
  461.  
  462. #if defined(BI_NAMESPACE)
  463. } // namespace OCF
  464. #endif
  465.  
  466.